home *** CD-ROM | disk | FTP | other *** search
- # include <ingres.h>
- # include <tree.h>
- # include <symbol.h>
- # include <pv.h>
- # include "globs.h"
- # include <sccs.h>
- # include <errors.h>
-
- SCCSID(@(#)byeval.c 8.3 12/18/85)
-
- /*
- ** BYEVAL - process aggregate function
- **
- ** Byeval is passed the root of the original query
- ** tree and the root of the aggregate function to
- ** be processed.
- **
- ** It first creates a temporary relation which will
- ** hold the aggregate result. The format of the relation
- ** is:
- ** _SYSxxxxxaa(count, by-dom1, ... , by-domn, ag1, ... , agm)
- **
- ** The relation is moved into the range table and will become
- ** a part of the query.
- **
- ** If there are any occurences of the variables
- ** from the by-domains, anywhere in the original query tree,
- ** the aggregate relation is linked on all by-domains in the
- ** original query tree.
- **
- ** If the aggregate is unique, multivariable, or has a
- ** qualification, then special processing is done.
- **
- ** If the aggregate is qualified then the by-domains are
- ** projected into the result relation. This guarantees that
- ** every value of the by-domains will be represented in the
- ** aggregate result.
- **
- ** If the aggregate is unique or multivariable, then another
- ** temporary relation is created and the values which will be
- ** aggregated; along with the by-domains, are retrieved into
- ** the temporary relation.
- **
- ** If unique, then duplicates are removed from the temporary relation.
- **
- ** Next the result relation for the aggregate is modified
- ** to hash in order to speed up the processing of the aggregate
- ** and guarantee that there are no duplicates in the bylist.
- **
- ** The aggregate is then run, and if a temporary relation was
- ** created (eg. unique or multivar aggregate) then it is destroyed.
- **
- ** Trace Flags:
- ** 42
- */
-
-
- QTREE *
- byeval(root, aghead, agvar)
- QTREE *root; /* root of orig query */
- QTREE *aghead; /* root of ag fcn sub-tree */
- int agvar; /* variable number assigned to this aggregate */
- {
-
- register QTREE *q, *ag, *resdom;
- QTREE *r;
- int temp_relnum, i, filled;
- QTREE *lnodv[MAXDOM+2], *save_node[MAXDOM+2];
- int agbuf[1+AGBUFSIZ/sizeof(int)];
- char nums[2];
- int relnum;
- QTREE *byhead, **alnp;
- int bydoms, bymap, primeag, srcmap;
- extern int derror();
- extern QTREE *makroot(), *makavar(), *makresdom(), *copytree();
- extern char *rnum_convert();
-
- # ifdef xDTR1
- if (tTf(42, -1))
- printf("BYEVAL\n");
- # endif
-
- ag = aghead;
- byhead = ag->left;
-
- /* first create the aggregate result relation */
- /* params for create */
-
- initp(); /* init globals for setp */
- setp(PV_STR,"0"); /* initial relstat field */
- relnum = rnum_alloc();
- setp(PV_STR,rnum_convert(relnum));
- setp(PV_STR,"count"); /* domain 1 - count field per BY value */
- setp(PV_STR,"i4"); /* format of count field */
-
- i = bydoms = lnode(byhead->left, lnodv, 0);
- lnodv[i] = 0;
- alnp = &lnodv[++i];
- i = lnode(byhead->right, lnodv, i);
- lnodv[i] = 0;
-
- domnam(lnodv, "by"); /* BY list domains */
- domnam(alnp, "ag"); /* aggregate value domains */
-
- call_dbu(mdCREATE, FALSE);
-
- De.de_rangev[agvar].relnum = relnum;
- # ifdef xDTR1
- if (tTf(42, 7))
- printf("agvar=%d,rel=%s\n", agvar, rnum_convert(relnum));
- # endif
-
- bymap = varfind(byhead->left, (QTREE *)NULL);
-
- /*
- ** Find all variables in the tree in which you are nested.
- ** Do not look at any other aggregates in the tree. Just in
- ** case the root is an aggregate, explicitly look at its
- ** two descendents.
- */
- srcmap = varfind(root->left, ag) | varfind(root->right, ag);
- # ifdef xDTR1
- if (tTf(42, 8))
- printf("bymap=%o,srcmap=%o\n", bymap, srcmap);
- # endif
-
- if (bymap & srcmap)
- modqual(root, lnodv, srcmap, agvar);
-
- /* if aggregate is unique or there is a qualification
- ** or aggregate is multi-var, then special processing is done */
-
- temp_relnum = NORESULT;
- filled = FALSE;
- primeag = prime(byhead->right);
- if (ag->right->sym.type != QLEND || ag->sym.value.sym_root.tvarc > 1 || primeag)
- {
- /* init a buffer for new tree components */
- initbuf((char *)agbuf, AGBUFSIZ, AGBUFFULL, derror);
-
- /* make a root for a new tree */
- q = makroot((char *)agbuf);
-
- /*
- ** Create a RESDOM for each by-domain in the original
- ** aggregate. Rather than using the existing by-domain
- ** function, a copy is used instead. This is necessary
- ** since that subtree might be needed later (if modqual())
- ** decided to use it. Decomp does not restore the trees
- ** it uses and thus the by-domains might be altered.
- */
- for (i = 0; r = lnodv[i]; i++)
- {
- resdom = makresdom((char *)agbuf, r);
- resdom->sym.value.sym_resdom.resno = i + 2;
- resdom->right = copytree(r->right, (char *)agbuf);
- resdom->left = q->left;
- q->left = resdom;
- }
- mapvar(q, 0); /* make maps on root */
- # ifdef xDTR1
- if (tTf(42, 2))
- {
- printf("byedomains\n");
- treepr(q);
- }
- # endif
-
- /* if agg is qualified, project by-domains into result */
- if (ag->right->sym.type != QLEND)
- {
- filled = TRUE;
- i = De.de_sourcevar; /* save value */
- decomp(q, mdRETR, relnum);
- De.de_sourcevar = i; /* restore value */
- }
-
- /* if agg is prime or multivar, compute into temp rel */
- if (ag->sym.value.sym_root.tvarc > 1 || primeag)
- {
- q->right = ag->right; /* give q the qualification */
- ag->right = De.de_qle; /* remove qualification from ag */
-
- /* put aop resdoms on tree */
- for (i = bydoms + 1; r = lnodv[i]; i++)
- {
- resdom = makresdom((char *)agbuf, r);
- resdom->right = r->right;
- resdom->left = q->left;
- q->left = resdom;
-
- /* make aop refer to temp relation */
- r->right = makavar(resdom, FREEVAR, i);
- }
-
- /* assign result domain numbers */
- for (resdom = q->left; resdom->sym.type != TREE; resdom = resdom->left)
- resdom->sym.value.sym_resdom.resno = --i;
-
- /*
- ** change by-list in agg to reference new source rel.
- ** Save the old bylist to be restored at the end of
- ** this aggregate.
- */
- for (i = 0; resdom = lnodv[i]; i++)
- {
- save_node[i] = resdom->right;
- resdom->right = makavar(resdom, FREEVAR, i + 1);
- }
-
- mapvar(q, 0);
- # ifdef xDTR1
- if (tTf(42, 3))
- {
- printf("new ag src\n");
- treepr(q);
- }
- # endif
-
- /* create temp relation */
- temp_relnum = mak_t_rel(q, "a", -1);
- decomp(q, mdRETR, temp_relnum);
- De.de_rangev[FREEVAR].relnum = temp_relnum;
- De.de_sourcevar = FREEVAR;
- if (primeag)
- removedups(FREEVAR);
- # ifdef xDTR1
- if (tTf(42, 4))
- {
- printf("new agg\n");
- treepr(ag);
- }
- # endif
- }
- }
-
- /* set up parameters for modify to hash */
- initp();
- setp(PV_STR, rnum_convert(relnum));
- setp(PV_STR, "hash"); /* modify the empty rel to hash */
- setp(PV_STR, "num"); /* code to indicate numeric domain names */
- nums[1] = '\0';
- for (i = 0; i < bydoms; i++)
- {
- nums[0] = i + 2;
- setp(PV_STR, nums);
- }
- setp(PV_STR, "");
-
- /* set up fill factor information */
- setp(PV_STR,"minpages");
- if (filled)
- {
- setp(PV_STR,"1");
- setp(PV_STR,"fillfactor");
- setp(PV_STR,"100");
- }
- else
- {
- setp(PV_STR,"10");
- }
- specclose(relnum);
- call_dbu(mdMODIFY, FALSE);
-
-
- De.de_newq = 1;
- De.de_newr = TRUE;
- call_ovqp(ag, mdRETR, relnum);
-
- De.de_newq = 0;
- /* if temp relation was used, destroy it */
- if (temp_relnum != NORESULT)
- {
- for (i = 0; resdom = lnodv[i]; i++)
- resdom->right = save_node[i];
- dstr_rel(temp_relnum);
- }
- }
-
-
-
-
- modqual(root, lnodv, srcmap, agvar)
- QTREE *root;
- QTREE *lnodv[];
- int srcmap;
- int agvar;
- {
- register QTREE *and_eq, *afcn;
- register int i;
- extern QTREE *copytree();
- extern char *need();
- register int len;
-
- # ifdef xDTR1
- if (tTf(42, 12))
- printf("modqual %o\n", srcmap);
- # endif
-
- for (i = 0; afcn = lnodv[i]; i++)
- {
- /* `AND' node */
- len = sizeof (struct rootnode) - sizeof (short);
- and_eq = (QTREE *) need(De.de_qbuf, QT_HDR_SIZ + len);
- and_eq->sym.type = AND;
- and_eq->sym.len = len;
- and_eq->sym.value.sym_root.tvarc = 0;
- and_eq->sym.value.sym_root.lvarc = 0;
- and_eq->sym.value.sym_root.lvarm = 0;
- and_eq->sym.value.sym_root.rvarm = 0;
- and_eq->right = root->right;
- root->right = and_eq;
-
- /* `EQ' node */
- len = sizeof (struct opnode);
- and_eq->left = (QTREE *) need(De.de_qbuf, QT_HDR_SIZ + len);
- and_eq = and_eq->left;
- and_eq->sym.type = BOP;
- and_eq->sym.len = len;
- and_eq->sym.value.sym_op.opno = opEQ;
-
- /* bydomain opEQ var */
- and_eq->right = copytree(afcn->right, De.de_qbuf); /* a-fcn (in Source) specifying BY domain */
- and_eq->left = makavar(afcn, agvar, i+2); /* VAR ref BY domain */
- }
- }
-